package filehelp

import (
	"archive/zip"
	"fmt"
	"io"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
)

// dir: 需要打包的本地文件夹路径
// dst: 保存压缩包的本地路径
func compressDir(dir string, dst string) error {
	zipFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE, 0660)
	if err != nil {
		return err
	}
	defer zipFile.Close()
	archive := zip.NewWriter(zipFile)
	defer archive.Close()
	return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
		if path == dir {
			return nil
		}
		info, _ := d.Info()
		h, _ := zip.FileInfoHeader(info)
		h.Name = strings.TrimPrefix(path, dir+"/")
		if info.IsDir() {
			h.Name += "/"
		} else {
			h.Method = zip.Deflate
		}
		writer, _ := archive.CreateHeader(h)
		if !info.IsDir() {
			srcFile, _ := os.Open(path)
			defer srcFile.Close()
			io.Copy(writer, srcFile)
		}
		return nil
	})
}

// unzip 解压压缩文件
// src: 需要解压的zip文件
// dest：解压的目标目录 如：./files
func decompressZip(src string) error {
	archive, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	dir := filepath.Dir(src)
	defer archive.Close()
	for _, f := range archive.File {
		filePath := filepath.Join(dir, f.Name)
		if f.FileInfo().IsDir() {
			os.MkdirAll(filePath, os.ModePerm)
			continue
		}
		if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
			return fmt.Errorf("failed to make directory (%v)", err)
		}
		dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
		if err != nil {
			return fmt.Errorf("failed to create file (%v)", err)
		}
		fileInArchive, err := f.Open()
		if err != nil {
			return fmt.Errorf("failed to open file in zip (%v)", err)
		}
		if _, err := io.Copy(dstFile, fileInArchive); err != nil {
			return fmt.Errorf("failed to copy file in zip (%v)", err)
		}
		dstFile.Close()
		fileInArchive.Close()
	}
	return nil
}
